/**
 * @fileOverview The "richcombo" plugin.
 */
VED.plugins.add( 'richcombo', {
   requires: 'floatpanel,listblock,button',

   beforeInit: function( editor ) {
      editor.ui.addHandler( VED.UI_RICHCOMBO, VED.ui.richCombo.handler );
   }
});

(function() {
   var template = '<span id="{id}"' +
      ' class="ved_combo ved_combo__{name} {cls}"' +
      ' role="presentation">' +
         '<span id="{id}_label" class="ved_combo_label">{label}</span>' +
         '<a class="ved_combo_button" hidefocus=true title="{title}" tabindex="-1"' +
         ( VED.env.gecko && VED.env.version >= 10900 && !VED.env.hc ? '' : '" href="javascript:void(\'{titleJs}\')"' ) +
         ' hidefocus="true"' +
         ' role="button"' +
         ' aria-labelledby="{id}_label"' +
         ' aria-haspopup="true"';

   // Some browsers don't cancel key events in the keydown but in the
   // keypress.
   // TODO: Check if really needed for Gecko+Mac.
   if ( VED.env.opera || ( VED.env.gecko && VED.env.mac ) )
      template += ' onkeypress="return false;"';

   // With Firefox, we need to force the button to redraw, otherwise it
   // will remain in the focus state.
   if ( VED.env.gecko )
      template += ' onblur="this.style.cssText = this.style.cssText;"';

   template +=
      ' onkeydown="return VED.tools.callFunction({keydownFn},event,this);"' +
      ' onmousedown="return VED.tools.callFunction({mousedownFn},event);" ' +
      ' onfocus="return VED.tools.callFunction({focusFn},event);" ' +
         ( VED.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188
            '="VED.tools.callFunction({clickFn},this);return false;">' +
         '<span id="{id}_text" class="ved_combo_text ved_combo_inlinelabel">{label}</span>' +
         '<span class="ved_combo_open">' +
            '<span class="ved_combo_arrow">' +
            // BLACK DOWN-POINTING TRIANGLE
   ( VED.env.hc ? '&#9660;' : VED.env.air ? '&nbsp;' : '' ) +
            '</span>' +
         '</span>' +
      '</a>' +
      '</span>';

   var rcomboTpl = VED.addTemplate( 'combo', template );

   VED.UI_RICHCOMBO = 'richcombo';

   /**
    * @class
    */
   VED.ui.richCombo = new Class({
      initialize: function( definition ) {
         // Copy all definition properties to this object.
         VED.tools.extend( this, definition,
         // Set defaults.
         {
            // The combo won't participate in toolbar grouping.
            canGroup: false,
            title: definition.label,
            modes: { wysiwyg:1 },
            editorFocus: 1
         });

         // We don't want the panel definition in this object.
         var panelDefinition = this.panel || {};
         delete this.panel;

         this.id = VED.tools.getNextNumber();

         this.document = ( panelDefinition.parent && panelDefinition.parent.getDocument() ) || VED.document;

         panelDefinition.className = 'ved_combopanel';
         panelDefinition.block = {
            multiSelect: panelDefinition.multiSelect,
            attributes: panelDefinition.attributes
         };
         panelDefinition.toolbarRelated = true;

         this._ = {
            panelDefinition: panelDefinition,
            items: {}
         };
      },

      renderHtml: function( editor ) {
         var output = [];
         this.render( editor, output );
         return output.join( '' );
      },

      render: function( editor, output ) {
         var env = VED.env;

         var id = 'ved_' + this.id;
         var clickFn = VED.tools.addFunction( function( el ) {

         // Restore locked selection in Opera.
         if ( selLocked ) {
            editor.unlockSelection( 1 );
            selLocked = 0;
         }

            instance.execute( el );
         }, this );

         var combo = this;
         var instance = {
            id: id,
            combo: this,
            focus: function() {
               var element = VED.document.getById( id ).getChild( 1 );
               element.focus();
            },
            execute: function( el ) {
               var _ = combo._;

               if ( _.state == VED.TRISTATE_DISABLED )
                  return;

               combo.createPanel( editor );

               if ( _.on ) {
                  _.panel.hide();
                  return;
               }

               combo.commit();
               var value = combo.getValue();
               if ( value )
                  _.list.mark( value );
               else
                  _.list.unmarkAll();

               _.panel.showBlock( combo.id, new VED.dom.element( el ), 4 );
            },
            clickFn: clickFn
         };

         function updateState() {
            var state = this.modes[ editor.mode ] ? VED.TRISTATE_OFF : VED.TRISTATE_DISABLED;
            this.setState( editor.readOnly && !this.readOnly ? VED.TRISTATE_DISABLED : state );
            this.setValue( '' );
         }

         editor.on( 'mode', updateState, this );
         // If this combo is sensitive to readOnly state, update it accordingly.
         !this.readOnly && editor.on( 'readOnly', updateState, this );

         var keyDownFn = VED.tools.addFunction( function( ev, element ) {
            ev = new VED.dom.event( ev );

            var keystroke = ev.getKeystroke();
            switch ( keystroke ) {
               case 13: // ENTER
               case 32: // SPACE
               case 40: // ARROW-DOWN
                  // Show panel
                  VED.tools.callFunction( clickFn, element );
                  break;
               default:
                  // Delegate the default behavior to toolbar button key handling.
                  instance.onkey( instance, keystroke );
            }

            // Avoid subsequent focus grab on editor document.
            ev.preventDefault();
         });

         var focusFn = VED.tools.addFunction( function() {
            instance.onfocus && instance.onfocus();
         });

         var selLocked = 0;
         var mouseDownFn = VED.tools.addFunction( function() {
            // Opera: lock to prevent loosing editable text selection when clicking on button.
            if ( VED.env.opera ) {
               var edt = editor.editable();
               if ( edt.isInline() && edt.hasFocus ) {
                  editor.lockSelection();
                  selLocked = 1;
               }
            }
         });

         // For clean up
         instance.keyDownFn = keyDownFn;

         var params = {
            id: id,
            name: this.name || this.command,
            label: this.label,
            title: this.title,
            cls: this.className || '',
            titleJs: env.gecko && env.version >= 10900 && !env.hc ? '' : ( this.title || '' ).replace( "'", '' ),
            keydownFn: keyDownFn,
            mousedownFn: mouseDownFn,
            focusFn: focusFn,
            clickFn: clickFn
         };

         rcomboTpl.output( params, output );

         if ( this.onRender )
            this.onRender();

         return instance;
      },

      createPanel: function( editor ) {
         if ( this._.panel )
            return;

         var panelDefinition = this._.panelDefinition,
            panelBlockDefinition = this._.panelDefinition.block,
            panelParentElement = panelDefinition.parent || VED.document.getBody(),
            namedPanelCls = 'ved_combopanel__' + this.name,
            panel = new VED.ui.floatPanel( editor, panelParentElement, panelDefinition ),
            list = panel.addListBlock( this.id, panelBlockDefinition ),
            me = this;

         panel.onShow = function() {
            this.element.addClass( namedPanelCls );

            me.setState( VED.TRISTATE_ON );

            me._.on = 1;

            me.editorFocus && editor.focus();

            if ( me.onOpen )
               me.onOpen();

            list.focus( !list.multiSelect && me.getValue() );
         };

         panel.onHide = function( preventOnClose ) {
            this.element.removeClass( namedPanelCls );

            me.setState( me.modes && me.modes[ editor.mode ] ? VED.TRISTATE_OFF : VED.TRISTATE_DISABLED );

            me._.on = 0;

            if ( !preventOnClose && me.onClose )
               me.onClose();
         };

         panel.onEscape = function() {
            // Hide drop-down with focus returned.
            panel.hide( 1 );
         };

         list.onClick = function( value, marked ) {

            if ( me.onClick )
               me.onClick.call( me, value, marked );

            panel.hide();
         };

         this._.panel = panel;
         this._.list = list;

         panel.getBlock( this.id ).onHide = function() {
            me._.on = 0;
            me.setState( VED.TRISTATE_OFF );
         };

         if ( this.init )
            this.init();
      },

      setValue: function( value, text ) {
         this._.value = value;

         var textElement = this.document.getById( 'ved_' + this.id + '_text' );
         if ( textElement ) {
            if ( !( value || text ) ) {
               text = this.label;
               textElement.addClass( 'ved_combo_inlinelabel' );
            } else
               textElement.removeClass( 'ved_combo_inlinelabel' );

            textElement.setText( typeof text != 'undefined' ? text : value );
         }
      },

      getValue: function() {
         return this._.value || '';
      },

      unmarkAll: function() {
         this._.list.unmarkAll();
      },

      mark: function( value ) {
         this._.list.mark( value );
      },

      hideItem: function( value ) {
         this._.list.hideItem( value );
      },

      hideGroup: function( groupTitle ) {
         this._.list.hideGroup( groupTitle );
      },

      showAll: function() {
         this._.list.showAll();
      },

      add: function( value, html, text ) {
         this._.items[ value ] = text || value;
         this._.list.add( value, html, text );
      },

      startGroup: function( title ) {
         this._.list.startGroup( title );
      },

      commit: function() {
         if ( !this._.committed ) {
            this._.list.commit();
            this._.committed = 1;
            VED.ui.fire( 'ready', this );
         }
         this._.committed = 1;
      },

      setState: function( state ) {
         if ( this._.state && this._.state == state )
            return;

         var el = this.document.getById( 'ved_' + this.id );
         el.setState( state, 'ved_combo' );

         state == VED.TRISTATE_DISABLED ?
            el.setAttribute( 'aria-disabled', true ) :
            el.removeAttribute( 'aria-disabled' );

         this._.state = state;
      },

      enable: function() {
         if ( this._.state && this._.state == VED.TRISTATE_DISABLED )
            this.setState( this._.lastState );
      },

      disable: function() {
         if ( this._.state != VED.TRISTATE_DISABLED ) {
            this._.lastState = this._.state;
            this.setState( VED.TRISTATE_DISABLED );
         }
      }
   });
   
   VED.ui.richCombo.handler = {
      create: function( definition ) {
         return new VED.ui.richCombo( definition );
      }
   };

   VED.ui.implement({
      addRichCombo: function( name, definition ) {
         this.add( name, VED.UI_RICHCOMBO, definition );
      }
   });

})();






